<script lang="ts" setup>
import type { ShareItem as ShareInfo } from '#/api/openapi/api';

import { computed, nextTick, ref, watch } from 'vue';

import { client } from '#/api';
import Button from '#/components/fluentui/Button.vue';
import Dialog from '#/components/fluentui/Dialog.vue';
import DialogBody from '#/components/fluentui/DialogBody.vue';

interface Props {
  modelValue?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: false,
});

const emit = defineEmits<{
  error: [message: string];
  shareFound: [shareInfo: ShareInfo];
  'update:modelValue': [value: boolean];
}>();

// 响应式状态
const isVisible = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value),
});

const shareCodeChars = ref(['', '', '', '']); // 4位分享码输入框
const shareCodeError = ref('');
// watch(shareCodeError, (newValue) => {
//   if (newValue) {
//     // 如果有错误，则光标移到第一个输入框
//     setTimeout(() => {
//     const firstInput = document.querySelector(
//       '[data-input-index="0"]',
//     ) as HTMLInputElement;
//     if (firstInput) {
//       firstInput.focus();
//       // firstInput.select(); // 选中内容以便覆盖
//     }
//     }, 500);
//   }
// });
const shareCodeErrorLine2 = ref('');
const isLoading = ref(false);

// 检查分享码是否完整
const isShareCodeComplete = computed(() => {
  return shareCodeChars.value.every((char) => char.trim() !== '');
});

// 4位分享码输入处理函数
const handleShareCodeInput = (index: number, event: Event) => {
  const target = event.target as HTMLInputElement;
  const value = target.value.toUpperCase();

  if (value && /^[A-Z0-9]$/.test(value)) {
    shareCodeChars.value[index] = value;
    shareCodeError.value = '';
    shareCodeErrorLine2.value = '';

    // 自动跳转到下一个输入框
    if (index < 3) {
      const nextInput = document.querySelector(
        `[data-input-index="${index + 1}"]`,
      ) as HTMLInputElement;
      if (nextInput) {
        nextInput.focus();
        nextInput.select(); // 选中内容以便覆盖
      }
    } else if (index === 3) {
      // 如果是最后一个输入框，自动提交
      nextTick(() => {
        if (isShareCodeComplete.value) {
          handleShareCodeConfirm();
        }
      });
    }
  } else if (value && value.length > 1) {
    // 处理多字符输入（可能是粘贴）
    const cleanValue = value.replaceAll(/[^A-Z0-9]/g, '');
    if (cleanValue.length > 0) {
      // 分发字符到各个输入框
      for (let i = 0; i < Math.min(4 - index, cleanValue.length); i++) {
        if (index + i < 4 && cleanValue[i]) {
          shareCodeChars.value[index + i] = cleanValue[i]!;
        }
      }
      // 聚焦到最后填充的输入框的下一个
      const targetIndex = Math.min(3, index + cleanValue.length - 1);
      if (targetIndex < 3) {
        const nextInput = document.querySelector(
          `[data-input-index="${targetIndex + 1}"]`,
        ) as HTMLInputElement;
        if (nextInput) {
          nextInput.focus();
        }
      }
    }
    target.value = shareCodeChars.value[index] ?? '';
  } else if (value && !/^[A-Z0-9]$/.test(value)) {
    // 不允许的字符，恢复原值
    target.value = shareCodeChars.value[index] ?? '';
  } else {
    shareCodeChars.value[index] = '';
  }
};

const handleShareCodeKeydown = (index: number, event: KeyboardEvent) => {
  if (event.key === 'Backspace') {
    if (!shareCodeChars.value[index] && index > 0) {
      // 如果当前输入框为空且按下退格键，跳转到前一个输入框并清空
      event.preventDefault();
      shareCodeChars.value[index - 1] = '';
      const prevInput = document.querySelector(
        `[data-input-index="${index - 1}"]`,
      ) as HTMLInputElement;
      if (prevInput) {
        prevInput.focus();
        prevInput.select();
      }
    } else if (shareCodeChars.value[index]) {
      // 如果当前输入框有内容，清空当前输入框
      shareCodeChars.value[index] = '';
    }
  } else if (event.key === 'Delete') {
    shareCodeChars.value[index] = '';
  } else if (event.key === 'ArrowLeft' && index > 0) {
    event.preventDefault();
    const prevInput = document.querySelector(
      `[data-input-index="${index - 1}"]`,
    ) as HTMLInputElement;
    if (prevInput) {
      prevInput.focus();
      prevInput.select();
    }
  } else if (event.key === 'ArrowRight' && index < 3) {
    event.preventDefault();
    const nextInput = document.querySelector(
      `[data-input-index="${index + 1}"]`,
    ) as HTMLInputElement;
    if (nextInput) {
      nextInput.focus();
      nextInput.select();
    }
  } else
    switch (event.key) {
      case 'End': {
        event.preventDefault();
        const lastInput = document.querySelector(
          '[data-input-index="3"]',
        ) as HTMLInputElement;
        if (lastInput) {
          lastInput.focus();
          lastInput.select();
        }

        break;
      }
      case 'Enter': {
        event.preventDefault();
        handleShareCodeConfirm();

        break;
      }
      case 'Escape': {
        event.preventDefault();
        handleCancel();

        break;
      }
      case 'Home': {
        event.preventDefault();
        const firstInput = document.querySelector(
          '[data-input-index="0"]',
        ) as HTMLInputElement;
        if (firstInput) {
          firstInput.focus();
          firstInput.select();
        }

        break;
      }
      default: {
        if (/^[a-z0-9]$/i.test(event.key)) {
          // 如果输入了字母或数字，先清空当前输入框
          shareCodeChars.value[index] = '';
        }
      }
    }
};

const handleShareCodePaste = (event: ClipboardEvent) => {
  event.preventDefault();
  const pastedText =
    event.clipboardData
      ?.getData('text')
      ?.toUpperCase()
      .replaceAll(/[^A-Z0-9]/g, '') || '';

  if (pastedText.length > 0) {
    // 清空所有输入框
    shareCodeChars.value = ['', '', '', ''];

    // 填充粘贴的内容
    for (let i = 0; i < Math.min(4, pastedText.length); i++) {
      shareCodeChars.value[i] = pastedText[i]!;
    }

    shareCodeError.value = '';
    shareCodeErrorLine2.value = '';

    // 聚焦到适当的位置
    const targetIndex = Math.min(3, pastedText.length);
    const targetInput = document.querySelector(
      `[data-input-index="${targetIndex}"]`,
    ) as HTMLInputElement;

    if (targetInput) {
      targetInput.focus();
      targetInput.select();
    }

    // 如果粘贴了完整的4位码，自动确认
    if (pastedText.length === 4) {
      nextTick(() => {
        handleShareCodeConfirm();
      });
    }
  }
};

const handleShareCodeConfirm = async () => {
  if (!isShareCodeComplete.value) {
    shareCodeError.value = '请输入完整的4位分享码';
    shareCodeErrorLine2.value = '';

    return;
  }

  const finalShareCode = shareCodeChars.value.join('');

  isLoading.value = true;
  shareCodeError.value = '';
  shareCodeErrorLine2.value = '';

  try {
    const { data: shareData } =
      await client.shareItem.getShareItemById(finalShareCode);
    if (!shareData) {
      shareCodeError.value = '分享码不存在或已过期，请检查后重试';
      shareCodeErrorLine2.value = '';

      return;
    }
    // 触发成功事件，传递分享信息
    emit('shareFound', shareData);
    // 关闭当前弹窗
    isVisible.value = false;
    // 重置表单
    resetForm();
  } catch (error) {
    shareCodeError.value = `获取分享信息失败，请检查分享码是否正确`;
    shareCodeErrorLine2.value = `${error}`;
    emit('error', '获取分享信息失败，请检查分享码是否正确');
  } finally {
    isLoading.value = false;
  }
};

const handleCancel = () => {
  isVisible.value = false;
  resetForm();
};

const resetForm = () => {
  shareCodeChars.value = ['', '', '', ''];
  shareCodeError.value = '';
  shareCodeErrorLine2.value = '';

  isLoading.value = false;
};

// 监听弹窗开启，聚焦第一个输入框
watch(isVisible, (newValue) => {
  if (newValue) {
    resetForm();
    nextTick(() => {
      const firstInput = document.querySelector(
        '[data-input-index="0"]',
      ) as HTMLInputElement;
      if (firstInput) {
        firstInput.focus();
      }
    });
  }
});
</script>

<template>
  <Dialog
    v-model="isVisible"
    type="modal"
    :prevent-close="isLoading"
    aria-labelledby="share-code-dialog-title"
  >
    <DialogBody>
      <div class="mx-auto mb-2 w-full max-w-md">
        <!-- 标题 -->
        <div class="mb-6 text-center">
          <h2
            id="share-code-dialog-title"
            class="mb-2 text-2xl font-bold text-gray-900 dark:text-gray-100"
          >
            请输入分享码
          </h2>
          <p class="text-gray-600 dark:text-gray-400">
            请输入4位分享码以获取文件
          </p>
        </div>

        <!-- 分享码输入框 -->
        <div class="mb-6">
          <div class="mb-4 flex justify-center space-x-3">
            <template v-for="(char, index) in shareCodeChars" :key="index">
              <div class="relative">
                <input
                  v-model="shareCodeChars[index]"
                  :data-input-index="index"
                  type="text"
                  maxlength="1"
                  autocomplete="off"
                  spellcheck="false"
                  class="input-code-box"
                  :class="{
                    'input-error': shareCodeError,
                    'input-filled': char && !shareCodeError,
                    'input-loading': isLoading,
                  }"
                  @input="handleShareCodeInput(index, $event)"
                  @keydown="handleShareCodeKeydown(index, $event)"
                  @paste="handleShareCodePaste"
                  @focus="shareCodeError = ''"
                  :disabled="isLoading"
                  :aria-label="`分享码第${index + 1}位`"
                  :aria-describedby="
                    shareCodeError ? 'share-code-error' : undefined
                  "
                />
                <!-- 输入指示器 -->
                <div
                  v-if="char"
                  class="absolute -right-1 -top-1 h-2 w-2 animate-ping rounded-full bg-green-500 opacity-0"
                  :class="{ 'opacity-100': char && !shareCodeError }"
                ></div>
              </div>
            </template>
          </div>

          <!-- 错误信息 -->
          <div
            id="share-code-error"
            class="animate-shake flex items-center justify-center space-x-2 text-sm text-red-500"
            role="alert"
            aria-live="polite"
            v-if="shareCodeErrorLine2"
          >
            <span>{{ shareCodeErrorLine2 }}</span>
          </div>
          <div
            v-if="shareCodeError"
            id="share-code-error"
            class="animate-shake mb-4 flex items-center justify-center space-x-2 text-sm text-red-500"
            role="alert"
            aria-live="polite"
          >
            <svg
              class="h-4 w-4 flex-shrink-0"
              fill="currentColor"
              viewBox="0 0 20 20"
            >
              <path
                fill-rule="evenodd"
                d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z"
                clip-rule="evenodd"
              />
            </svg>
            <span>{{ shareCodeError }}</span>
          </div>

          <!-- 提示信息 -->
          <div class="space-y-1 text-center">
            <div class="text-xs text-gray-500 dark:text-gray-400">
              支持粘贴完整分享码 • 按 Enter 确认 • 按 Esc 取消
            </div>
            <div class="text-xs text-gray-400 dark:text-gray-500">
              使用方向键或 Tab 键导航，支持 Home/End 快速跳转
            </div>
          </div>

          <!-- 进度指示器 -->
          <div class="mt-4 flex justify-center space-x-1">
            <template
              v-for="(char, _progressIndex) in shareCodeChars"
              :key="`progress-${_progressIndex}`"
            >
              <div
                class="h-1 w-6 rounded-full transition-all duration-200"
                :class="{
                  'bg-blue-500': char,
                  'bg-gray-200 dark:bg-gray-700': !char,
                }"
              ></div>
            </template>
          </div>
        </div>

        <!-- 操作按钮 -->
        <div class="flex space-x-3">
          <Button
            appearance="subtle"
            class="flex-1"
            @click="handleCancel"
            :disabled="isLoading"
            title="按 Esc 快速取消"
          >
            取消
          </Button>
          <Button
            appearance="primary"
            class="relative flex-1"
            @click="handleShareCodeConfirm"
            :disabled="!isShareCodeComplete || isLoading"
            title="按 Enter 快速确认"
          >
            <span
              v-if="isLoading"
              class="flex items-center justify-center space-x-2"
            >
              <svg class="h-4 w-4 animate-spin" fill="none" viewBox="0 0 24 24">
                <circle
                  class="opacity-25"
                  cx="12"
                  cy="12"
                  r="10"
                  stroke="currentColor"
                  stroke-width="4"
                />
                <path
                  class="opacity-75"
                  fill="currentColor"
                  d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
                />
              </svg>
              <span>获取中...</span>
            </span>
            <span v-else>确认获取</span>
          </Button>
        </div>
      </div>
    </DialogBody>
  </Dialog>
</template>

<style scoped>
/* 动画效果 */
@keyframes shake {
  0%,
  100% {
    transform: translateX(0);
  }

  10%,
  30%,
  50%,
  70%,
  90% {
    transform: translateX(-2px);
  }

  20%,
  40%,
  60%,
  80% {
    transform: translateX(2px);
  }
}

/* 响应式设计 */
@media (width <= 640px) {
  .input-code-box {
    @apply h-12 w-12 text-lg;
  }
}

/* 减少动画支持 */
@media (prefers-reduced-motion: reduce) {
  .input-code-box {
    transition: none;
  }

  .input-code-box:focus {
    transform: none;
  }

  .animate-shake {
    animation: none;
  }
}

/* 输入框样式 */
.input-code-box {
  @apply h-14 w-14 rounded-xl border-2 border-gray-300 bg-white text-center text-xl font-bold text-gray-900 transition-all duration-200 ease-in-out focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500/20 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100;
}

.input-code-box:focus {
  box-shadow: 0 8px 25px rgb(59 130 246 / 15%);
  transform: scale(1.05);
}

.input-code-box:disabled {
  @apply cursor-not-allowed opacity-60;
}

.input-code-box::placeholder {
  @apply text-sm font-normal text-gray-400 dark:text-gray-500;
}

/* 状态样式 */
.input-error {
  @apply border-red-500 bg-red-50 focus:border-red-500 focus:ring-red-500/20 dark:bg-red-900/20;
}

.input-filled {
  @apply border-green-500 bg-green-50 dark:bg-green-900/20;
}

.input-loading {
  @apply border-blue-300 bg-blue-50 dark:bg-blue-900/20;
}

.animate-shake {
  animation: shake 0.5s ease-in-out;
}

/* 输入框悬停效果 */
.input-code-box:hover:not(:disabled) {
  @apply border-blue-400 dark:border-blue-400;
}
</style>
